package fr.afcepf.atod18.dao;

import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaQuery;

import org.springframework.transaction.annotation.Transactional;

public abstract class GenericDAO<T> {

    private EntityManager em;

    @PersistenceContext
    public void setEntityManager(EntityManager entityManager) {
        this.em = entityManager;
    }

    private Class<T> entityClass;

    public GenericDAO(Class<T> entityClass) {
        this.entityClass = entityClass;
    }
    
    @Transactional
    public void save(T entity) {
        em.persist(entity);
        em.flush();
    }
        
    @Transactional
    public void delete(T entity) {
        T toRemoved = em.merge(entity);
        em.remove(toRemoved);
    }

    @Transactional
    public T update(T entity) {
        T toUpdate = em.merge(entity);
        return toUpdate;
    }
    
    public T find(int entityID) {
        return em.find(entityClass, entityID);
    }

    // car jpa ne possede pas de methode
    // em.getCriteriaBuilder().createQuery()<T> method
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public List<T> findAll() {
        CriteriaQuery cq = em.getCriteriaBuilder().createQuery();
        cq.select(cq.from(entityClass));
        return em.createQuery(cq).getResultList();
    }

    // car jpa ne possede pas de methode
    // ery.getSingleResult()<T> method
    @SuppressWarnings("unchecked")
    protected T findOneResult(String namedQuery, Map<String, Object> parameters) {
        T result = null;

        try {
            Query query = em.createNamedQuery(namedQuery);

            // ssi parametres pas null et non vide
            if (parameters != null && !parameters.isEmpty()) {
                populateQueryParameters(query, parameters);
            }

            result = (T) query.getSingleResult();

        } catch (Exception e) {
            System.out.println("Error while running query: " + e.getMessage());
            e.printStackTrace();
        }

        return result;
    }

    private void populateQueryParameters(Query query,
            Map<String, Object> parameters) {

        for (Entry<String, Object> entry : parameters.entrySet()) {
            query.setParameter(entry.getKey(), entry.getValue());
        }
    }
}